package com.xdf.whiteaccount.config;

import com.xdf.whiteaccount.config.properties.DbConfig;
import com.xdf.whiteaccount.config.datasource.DynamicDataSource;
import com.xdf.whiteaccount.config.properties.PrimaryDbParam;
import com.xdf.whiteaccount.enums.DatasourceKey;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * @program: white-account
 * @description: 数据源配置
 * @author: 张柯
 * @create: 2021-06-11 09:11
 **/
@Configuration
@MapperScan(basePackages = {"com.xdf.whiteaccount.clouddao", "com.xdf.whiteaccount.dao", "com.xdf.whiteaccount.mobiledao"},
        sqlSessionFactoryRef = "sqlSessionFactory",
        sqlSessionTemplateRef = "sqlSessionTemplate")
public class DataSourceConfig {
    @Autowired
    private PrimaryDbParam primaryDbParam;

    /**
     * 数据源
     *
     * @return
     */
    @Bean(value = "dataSource")
    @Primary
    public DynamicDataSource dynamicDataSource() throws Exception {
        DynamicDataSource ds = DynamicDataSource.getInstance();
        Map<Object, Object> map = new HashMap<>();
        map.put(DatasourceKey.PRIMARY_KEY, DbConfig.getDataSource(DbConfig.builder()
                .driverClassName(primaryDbParam.getDriverClassName())
                .url(primaryDbParam.getUrl())
                .username(primaryDbParam.getUsername())
                .password(primaryDbParam.getPassword())
                .loginTimeout(primaryDbParam.getLoginTimeout())
                .validationQuery(primaryDbParam.getValidationQuery())
                .idleTimeout(primaryDbParam.getIdleTimeout())
                .minimumIdle(primaryDbParam.getMinimumIdle())
                .timeBetweenEvictionRunsMillis(primaryDbParam.getTimeBetweenEvictionRunsMillis())
                .connectionTimeout(primaryDbParam.getConnectionTimeout())
                .maxLifeTime(primaryDbParam.getMaxLifeTime())
                .maximumPoolSize(primaryDbParam.getMaximumPoolSize())
                .testOnBorrow(primaryDbParam.isTestOnBorrow())
                .initializationFailTimeout(primaryDbParam.getInitializationFailTimeout())
                .build()));
        ds.setTargetDataSources(map);
        return ds;
    }

    /**
     * 事务处理器
     *
     * @param dataSource
     * @return
     */
    @Bean("transactionManager")
    @Order(3)
    public DataSourceTransactionManager transactionManager(@Qualifier("dataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    /**
     * 编程式事务管理模板
     * @param transactionManager
     * @return
     */
    @Bean("transactionTemplate")
    @Order(4)
    public TransactionTemplate transactionTemplate(@Qualifier("transactionManager") DataSourceTransactionManager transactionManager) {
        TransactionTemplate template = new TransactionTemplate(transactionManager);
        template.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW);
        return template;
    }

    /**
     * @param dataSource
     * @return
     * @throws Exception
     */
    @Bean("sqlSessionFactory")
    public SqlSessionFactory getSqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:*mapping/*.xml"));
        return bean.getObject();
    }

    /**
     * @param sqlSessionFactory
     * @return
     */
    @Bean("sqlSessionTemplate")
    public SqlSessionTemplate getSqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}
